/*	Copyright 2007 - Xavier Baro (xbaro@cvc.uab.cat)

	This file is part of eapmlib.

    Eapmlib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or any 
	later version.

    Eapmlib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __POPULATION_H__
#define __POPULATION_H__

#include "EvolutiveLib.h"
#include "Chromosome.h"
#include <vector>

namespace Evolutive {

	//! Defines the sorting orders
	enum EVOLUTIVELIB_API SORT_ORDER {SORT_ASC,SORT_DESC};

	//! Defines the diversity criteria
	enum EVOLUTIVELIB_API DIVERSITY_CRITERIA {DIV_NONE,DIV_PROB,DIV_HAMMING};

	//! Defines the class where the scores are stored
	class EVOLUTIVELIB_API CScoreStruct
	{
	public:
		double Value;
		unsigned int Idx;
	};

	//! Defines the data type for the vector that stores the scores
	class EVOLUTIVELIB_API CScoresVector : public std::vector<CScoreStruct>
	{
	};

	//! Comparation function for the ascendant sorting process
	inline bool AscComp ( CScoreStruct elem1, CScoreStruct elem2 )
	{
	   return elem1.Value < elem2.Value;
	}
	
	//! Comparation function for the descendant sorting process
	inline bool DescComp ( CScoreStruct elem1, CScoreStruct elem2 )
	{
	   return elem1.Value > elem2.Value;
	}

	//! Class to manage populations of chromosomes.
	class EVOLUTIVELIB_API CPopulation
	{
		//! Methods	
	public:
		//! Default constructor
		CPopulation(void);

		//! Default destructor
		virtual ~CPopulation(void);
		
		//! Initialize the population
		void Initialize(int PopSize,int NumBits);
		void Initialize(int PopSize,int NumBits,CODING_METHOD CodMethod);
		void Initialize(int PopSize,int NumFields,int *BitsPerField);
		void Initialize(int PopSize,int NumFields,int *BitsPerField,CODING_METHOD CodMethod);
				
		//! Clear the scores vector
		void ClearScores(void);

		//! Add a new score
		void AddScore(unsigned int Idx,double Value);

		//! Sort the scores
		void SortPopulationScores(SORT_ORDER Order);

		//! Select the elitism individuals
		void SelectElitistMembers(void);

		//! Add the elitist members of the population
		void AddElitistMembers(void);

		//! Sets the number of elitist individuals
		void SetNumElitist(int NumIndividuals);

		//! Operators overload
		CChromosome& operator[] (unsigned int Idx);

		//! Get the number of individuals, including the elitist individuals
		int GetPopulationSize(void);

		//! Returns the number of updatable individuals (all except the elisist)
		int GetPopulationUpdSize(void);

		//! Returns a pointer to a Chromosome
		CChromosome* GetChromosomePtr(unsigned int Idx);

		//! Returns a pointer to a Chromosome, using the sorted score list
		CChromosome* GetSortedChromosomePtr(unsigned int Idx);

		//! Returns the score of a certain Chromosome, using the sorted score list
		double GetSortedScoreVal(unsigned int Idx);		

		//! Returns the score and value from the sorted vector
		CScoreStruct& GetSortedScore(unsigned int Idx);

		//! Selects the diversity criteria
		void SetDiversityCriteria(DIVERSITY_CRITERIA Criteria);

		//! Loads a population from a file
		void LoadFromFile(string FileName,int NumPars,int *NumBits,CODING_METHOD CodMethod);

		//! Returns a flag informing when the population have score values
		bool IsScored(void);

		//! Export the population to a file
		void Export(string FileName);

		//! Assign a codification method
		void SetCodMethod(CODING_METHOD CodMethod);

	private:
		//! Create the necessary number of individuals
		void AllocIndividuals(int NumIndividuals);

		//! Count the number of lines in a file
		int GetNumFilesFromFile(string FileName);

		//! Attributes
	private:
		//! Number of individuals in the population
		unsigned int m_PopSize;

		//! Vector with the individuals
		CChromosome *m_Population;	
		
		//! Population score		
		CScoresVector *m_PopScores;

		//! Population diversity
		CScoresVector *m_PopDiversity;

		//! Population fitness
		CScoresVector *m_PopFitness;

		//! Number of elistist individuals
		int m_NumElitist;		

		//! Elistist individuals
		CChromosome *m_ElitistInd;

		//! Diversity criteria
		DIVERSITY_CRITERIA m_DiversityCriteria;
	};


}

#endif //__POPULATION_H__
